package de.gameduell.framework.game.billard.action {
	import de.gameduell.framework.game.billard.controller.AnimationController;
	import de.gameduell.framework.game.billard.controller.IBillardController;
	import de.gameduell.framework.game.billard.controller.PhysicController;
	import de.gameduell.framework.game.billard.event.AnimationEvent;
	import de.gameduell.framework.game.billard.event.HitActionEvent;
	import de.gameduell.framework.game.billard.event.PhysicEvent;
	import de.gameduell.framework.game.billard.model.ShootData;
	import de.gameduell.framework.queue.ActionEvent;
	import de.gameduell.framework.queue.GDActionQueue;
	import de.gameduell.framework.queue.IGDAction;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import org.cove.ape.Vector;	

	/**
	 * action wich starts with the calculation of a hit and ends with
	 * the end of the ball animation needed for queueing
	 */
	public class HitWhiteBallAction extends EventDispatcher implements IGDAction {
		/** saved strength for the hit */
		private var strength:Number;
		/** saved angle for the hit */
		private var angle:Number;
		/** saved hitPoint for the hit */
		private var hitPoint:Vector;
		/** saved direction for the hit */
		private var direction:Vector;
		/** controller that manages the different pbillardengine instances*/
		private var physicController:PhysicController;
		/** queue that manages the actions to avoid timing problems*/
		private var _actionQueue:GDActionQueue;
		/** model that holds the shoot parameters*/
		private var shootData:ShootData;
		/** controller to manage the ball animation*/
		private var animationController:AnimationController
		/** event dispatch controller */
		private var controller:IBillardController;

		/**
		 * constructor
		 */
		public function HitWhiteBallAction(aController:IBillardController,aDirection:Vector,aHitPoint:Vector,aAngle:Number,aStrength:Number) {
			controller = aController;
			physicController = aController.physicController;	
			shootData = aController.shootData;	
			_actionQueue = GDActionQueue.getInstance();	
			animationController = aController.animationController;		
			direction = aDirection;
			strength = aStrength;
			hitPoint = aHitPoint;
			angle = aAngle;
					
			invoke();
		}
		
		/**
		 * called when the queue animation is over
		 * 
		 * @param event PhysicEvent.QUEUE_SHOT
		 */
		private function onQueueShot(event:Event):void{	
			animationController.addEventListener(AnimationEvent.ANIMATION_OVER, onAnimationOver);
			animationController.start();
		}
		
		/**
		 * called when the ball animation is over
		 * 
		 * @param event AnimationEvent.ANIMATION_OVER
		 */
		private function onAnimationOver(event:Event):void{
			animationController.removeEventListener(AnimationEvent.ANIMATION_OVER, onAnimationOver);
			dispatchEvent(new ActionEvent(ActionEvent.DONE));
			
			// blocking flag = false
			controller.dispatchEvent(new HitActionEvent(HitActionEvent.HIT_WHITEBALL_ACTION_FINISHED));
		}
		
		/**
		 * called by the action queue to compute the action
		 */
		public function compute():void {
			// blocking flag = true					
			controller.dispatchEvent(new HitActionEvent(HitActionEvent.HIT_WHITEBALL_ACTION_STARTED));

			physicController.addEventListener(PhysicEvent.QUEUE_SHOT, onQueueShot);
			shootData.direction = direction;
			shootData.hitPoint 	= hitPoint;
			shootData.angle		= angle;
			shootData.strength  = strength;
			physicController.hitWhiteBall();		
		}
		
		/**
		 * adds the action to the queue
		 */
		public function invoke():void {
			_actionQueue.add(this);
		}
		
		/**
		 * returns the description of the action
		 * 
		 * @return description of the action
		 */
		public function get description():String {
			return "HitWhiteBallAction: direction: "+direction+" strength: "+strength+ " hitpoint: " + hitPoint + " angle: "+angle;
		}
	}
}
